using System.Windows.Forms;
using WindowsLive.Writer.Api;
using Nuane.Posterous;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace Writerous
{
    [WriterPlugin("321ac130-3b10-489b-a9a9-20ab1b0ea112", "Writerous",
        PublisherUrl = "http://writerous.codeplex.com",
        Description = "Allows you to post to Posterous from Live Writer",
        ImagePath = "writer.png",
        HasEditableOptions = true)]

    public class WriterousPlugin : PublishNotificationHook
    {
        private PluginSettings m_default;
        private string imgTagPattern = @"<img.*?src=""(?<url>.*?)"".*?>";
        private string imgFilePattern = @"src[^>]*[^/].(?:jpg|gif|png)(?:\""|\')";
        private string aTagPattern = @"<a.*?href=[""'](?<url>.*?)[""'].*?>(?<name>.*?)</a>";

        public override void Initialize(IProperties pluginOptions)
        {
            base.Initialize(pluginOptions);
            m_default = new PluginSettings(pluginOptions);
        }

        public override void EditOptions(IWin32Window dialogOwner)
        {
            frmOptions op = new frmOptions(m_default);
            op.ShowDialog();
        }

        public override bool OnPrePublish(IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish)
        {
            if (!publish)
                return false;

            if (m_default.EmailAddress.Length == 0 ||
                m_default.Password.Length == 0 ||
                m_default.SiteId == -1)
            {
                frmOptions op = new frmOptions(m_default);
                op.ShowDialog();
                if (op.DialogResult == DialogResult.Cancel)
                {
                    return false;
                }
            }
            IPostInfo info = publishingContext.PostInfo;
            PosterousSession session = new PosterousSession(m_default.EmailAddress, m_default.Password);
            session.ApplicationName = "Writerous";
            session.ApplicationUri = new Uri("http://writerous.codeplex.com");
            
            PosterousNewPost newPost = new PosterousNewPost();
            newPost.Title = info.Title;
            newPost.Body = info.Contents;
            string tags = "";
            foreach (var category in info.Categories)
            {
                if (!string.IsNullOrEmpty(tags))
                    tags += ", ";
                tags += category.Name;
            }
            if (!string.IsNullOrEmpty(tags))
                tags += ", ";
            tags += info.Keywords;
            newPost.Tags = tags;
            newPost.AutoPost = m_default.AutoPost;
            // Get the images from the blog post.
            GetImages(newPost);

            // Get the other file types supported by Posterous.com: http://posterous.com/faq/
            GetOtherFileTypes(newPost);            

            try
            {                
                PosterousPostInfo postInfo;
                using (frmPublishing pub = new frmPublishing(newPost, session, m_default.SiteId))
                {
                    // Start publishing
                    pub.GoBatman();
                    // Show the publishing dialog
                    pub.ShowDialog();            
                    // Grab the published post
                    postInfo = pub.m_publishedPost;
                }
                if (postInfo != null)
                {
                    frmSuccess success = new frmSuccess(postInfo);
                    // Disaply the dialog allowing the user to go to their successfully published post
                    success.ShowDialog();
                }
            }
            catch (Exception ex)
            {
                PluginDiagnostics.LogException(ex);
                PluginDiagnostics.DisplayError("There was an error publishing", ex.Message);
                return false;
            }

            return m_default.PostToBlog;
        }

        private void GetOtherFileTypes(PosterousNewPost newPost)
        {
            // Supported files are:
            // doc, ppt, pdf, jpg, gif, png, mp3, avi, mpg.
            string[] supportedExtensions = { ".doc", ".ppt", ".pdf", ".mp3", ".avi", ".mpg" };
            string tempPath = Path.GetTempPath();
            DirectoryInfo tempFolder = new DirectoryInfo(tempPath);
            DirectoryInfo liveWriterFolder;
            DirectoryInfo filesFolder;
            var writerFolders = from folders in tempFolder.GetDirectories()
                                where folders.Name.ToLower().StartsWith("windowslivewriter")
                                select folders;
            liveWriterFolder = writerFolders.First();
            filesFolder = liveWriterFolder.GetDirectories().First(p => p.Name.ToLower().StartsWith("supfiles"));
            
            var files = from file in filesFolder.GetFiles()
                        where supportedExtensions.Contains(file.Extension.ToLower())
                        select file;

            foreach (var file in files)
            {
                newPost.Files.Add(file.FullName);
            }
        }

        private void GetImages(PosterousNewPost newPost)
        {
            FileInfo[] images = GetImageFileInfos();
            Regex r_aTags = new Regex(aTagPattern, RegexOptions.IgnoreCase);
            MatchCollection m_aTags = r_aTags.Matches(newPost.Body);
            newPost.Body = CheckAndRemoveThumbnails(m_aTags, newPost.Body);

            Regex r_imgFiles = new Regex(imgFilePattern, RegexOptions.IgnoreCase);
            Regex r_imgTags = new Regex(imgTagPattern, RegexOptions.IgnoreCase);
            MatchCollection m_imgfiles = r_imgFiles.Matches(newPost.Body);
            MatchCollection m_imgtags = r_imgTags.Matches(newPost.Body);
            
            newPost.Body = StripNonHTTPImages(m_imgtags, newPost.Body);     
            foreach (var image in images)
            {
                foreach (Match match in m_imgfiles)
                {
                    if (match.Groups[0].Value.Contains(image.Name))
                    {
                        newPost.Files.Add(image.FullName);
                        break;
                    }
                }
            }            
        }

        private string CheckAndRemoveThumbnails(MatchCollection m_aTags, string body)
        {
            foreach (Match match in m_aTags)
            {
                if (match.Groups["name"].Value.ToLower().Contains("_thumb.")||
                    match.Groups["name"].Value.ToLower().Contains("_tn.")||
                    match.Groups["name"].Value.ToLower().Contains("_small."))
                {
                    // Get the <img> tag from the given match
                    string imgTag = match.Groups["name"].Value;
                    string thumbURL = match.Groups["url"].Value;
                    string newImgSrc = string.Format("src=\"{0}\"", thumbURL);
                    imgTag = Regex.Replace(imgTag, imgFilePattern, newImgSrc);
                    body = body.Replace(match.Groups[0].Value, imgTag);
                }
            }
            return body;
        }

        private string StripNonHTTPImages(MatchCollection m_imgtags, string postBody)
        {
            foreach (Match match in m_imgtags)
            {
                if (!match.Groups["url"].Value.ToLower().StartsWith("http"))
                {
                    postBody = postBody.Replace(match.Groups[0].Value, string.Empty);
                }
            }
            return postBody;
        }

        private FileInfo[] GetImageFileInfos()
        {
            string tempPath = Path.GetTempPath();
            DirectoryInfo tempFolder = new DirectoryInfo(tempPath);
            DirectoryInfo liveWriterFolder;
            DirectoryInfo filesFolder;
            var writerFolders = from folders in tempFolder.GetDirectories()
                                where folders.Name.ToLower().StartsWith("windowslivewriter")
                                select folders;

            liveWriterFolder = writerFolders.First();
            filesFolder = liveWriterFolder.GetDirectories().First(p => p.Name.ToLower().StartsWith("supfiles"));

            var result = from files in filesFolder.GetFiles()
                         where files.Extension.ToLower().Contains("jpg") ||
                         files.Extension.ToLower().Contains("png") ||
                         files.Extension.ToLower().Contains("gif") 
                         select files;
            return result.ToArray();
        }
    }
}
